home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mh / mh-6.8 / zotnet / mf / mmuu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-14  |  11.5 KB  |  547 lines

  1. /* mmuu.c - routines to filter MMDF to UUCP mailboxes */
  2.  
  3. #include "mf.h"
  4. #include "../tws/tws.h"
  5. #include <stdio.h>
  6. #include "../mts/mts.h"
  7. #include <ctype.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10.  
  11. /*   */
  12.  
  13. static struct header {
  14.     char   *h_name;
  15.     int     h_type;
  16. }                       headers[] = {
  17.                             "From", HFROM,
  18.                             "Sender", HSNDR,
  19.                             "Reply-To", HADDR,
  20.                             "To", HADDR,
  21.                             "cc", HADDR,
  22.                             "Bcc", HADDR,
  23.                             "Resent-From", HADDR,
  24.                             "Resent-Sender", HADDR,
  25.                             "Resent-Reply-To", HADDR,
  26.                             "Resent-To", HADDR,
  27.                             "Resent-cc", HADDR,
  28.                             "Resent-Bcc", HADDR,
  29.                             "Date", HDATE,
  30.                             "Resent-Date", HDATE,
  31.                             NULL, HOTHR
  32. };
  33.  
  34.  
  35. static char buffer[BUFSIZ],
  36.             tmpbuf[BUFSIZ];
  37.  
  38. long    time ();
  39. char   *ctime ();
  40.  
  41. /*   */
  42.  
  43. /* 
  44.  *    mmdf2uucp() - given a file descriptor to a mmdf mailbox, filter
  45.  *    its contents to the file descriptor for a mmdf mailbox.  Returns
  46.  *    non-zero on error (see mf.h for values)
  47.  *
  48.  *    It is assumed that the caller will have made sure that the necessary
  49.  *    locking has been performed on the output fd.
  50.  */
  51.  
  52. int    mmdf2uucp (infd, outfd, nodelim)
  53. int     infd,
  54.         outfd,
  55.         nodelim;
  56. {
  57.     int     fd,
  58.             result;
  59.     struct stat st;
  60.     FILE * in, *out;
  61.  
  62.     if (fstat (infd, &st) == NOTOK || fstat (outfd, &st) == NOTOK)
  63.     return MFPRM;
  64.     if ((in = fdopen (infd, "r")) == NULL
  65.         || (out = fdopen (outfd, "w")) == NULL)
  66.     return MFSIO;
  67.  
  68.     result = mmuu (in, out, nodelim);
  69.  
  70.     /* for STDIO - free up some fp:s */
  71.     fd = dup (fileno (in));
  72.     fclose (in);
  73.     dup2 (fd, infd);
  74.     close (fd);
  75.  
  76.     fd = dup (fileno (out));
  77.     fclose (out);
  78.     dup2 (fd, outfd);
  79.     close (fd);
  80.  
  81.     return result;
  82. }
  83.  
  84. /*   */
  85.  
  86. static int  mmuu (in, out, nodelim)
  87. FILE   *in,
  88.        *out;
  89. int     nodelim;
  90. {
  91.     int     i,
  92.             tmp_fd;
  93.     FILE   *tmp;
  94.  
  95.     for (tmp_fd = NOTOK;;) {
  96.     if ((i = mmdf_file (&tmp_fd, in, &tmp, nodelim)) == DONE)
  97.         break;
  98.     else
  99.         if (i != OK)
  100.         return i;
  101.     if ((i = mmdf_headers (tmp, out, nodelim)) != OK)
  102.         return mmdf_die (i, tmp, in, out, nodelim);
  103.     if ((i = mmdf_text (tmp, out, nodelim)) != OK)
  104.         return mmdf_die (i, tmp, in, out, nodelim);
  105.     }
  106.  
  107.     fflush (out);
  108.  
  109.     return (ferror (in) || ferror (out) ? MFERR : MFOK);
  110. }
  111.  
  112. /*   */
  113.  
  114. static int  mmdf_file (tmp_fd, in, tmp, nodelim)
  115. int    *tmp_fd,
  116.         nodelim;
  117. FILE * in, **tmp;
  118. {
  119.     int     done,
  120.             fd;
  121.     char    tmpfil[LINESIZ];
  122.     FILE * out;
  123.  
  124.     if (nodelim)
  125.     if (*tmp_fd != NOTOK)
  126.         return DONE;
  127.     else
  128.         if ((*tmp_fd = dup (fileno (in))) == NOTOK)
  129.         return MFERR;
  130.         else
  131.         if ((*tmp = fdopen (*tmp_fd, "r")) == NULL) {
  132.             close (*tmp_fd);
  133.             return MFERR;
  134.         }
  135.         else
  136.             return OK;
  137.  
  138.     if (fgets (tmpbuf, sizeof tmpbuf, in) == NULL)
  139.     return DONE;
  140.     if (!isdlm1 (tmpbuf))
  141.     return MFDLM;
  142.  
  143.     strcpy (tmpfil, "/tmp/mmuuXXXXXX");
  144.     unlink (mktemp (tmpfil));
  145.     if ((fd = creat (tmpfil, TMPMODE)) == NOTOK)
  146.     return MFERR;
  147.     close (fd);
  148.  
  149.     if ((fd = open (tmpfil, 2)) == NOTOK)
  150.     return MFERR;
  151.     if ((out = fdopen (fd, "w")) == NULL) {
  152.     close (fd);
  153.     return MFERR;
  154.     }
  155.     unlink (tmpfil);
  156.  
  157.     if ((*tmp_fd = dup (fd)) == NOTOK) {
  158.     close (fd);
  159.     return MFERR;
  160.     }
  161.     if ((*tmp = fdopen (*tmp_fd, "r")) == NULL) {
  162.     close (fd);
  163.     close (*tmp_fd);
  164.     return MFERR;
  165.     }
  166.  
  167. /*   */
  168.  
  169.     for (done = FALSE;;) {
  170.     if (fgets (tmpbuf, sizeof tmpbuf, in) == NULL)
  171.         return MFDLM;
  172.     if (done && isdlm2 (tmpbuf))
  173.         break;
  174.     done = tmpbuf[strlen (tmpbuf) - 1] == '\n';
  175.     fputs (tmpbuf, out);
  176.     }
  177.  
  178.     fclose (out);
  179.     fseek (*tmp, 0L, 0);
  180.     return OK;
  181. }
  182.  
  183. /*   */
  184.  
  185. static int  mmdf_headers (in, out, nodelim)
  186.             FILE * in, *out;
  187. int     nodelim;
  188. {
  189.     int     fd,
  190.             i,
  191.             tmp_fd;
  192.     char   *cp,
  193.             line[BUFSIZ],
  194.             from[LINESIZ],
  195.             date[LINESIZ],
  196.             tmpfil[LINESIZ];
  197.     FILE * tmp;
  198.  
  199.     *from = *date = NULL;
  200.  
  201.     strcpy (tmpfil, "/tmp/mmuuXXXXXX");
  202.     unlink (mktemp (tmpfil));
  203.     if ((fd = creat (tmpfil, TMPMODE)) == NOTOK)
  204.     return MFERR;
  205.     close (fd);
  206.     if ((tmp_fd = open (tmpfil, 2)) == NOTOK)
  207.     return MFERR;
  208.     unlink (tmpfil);
  209.  
  210.     if ((fd = dup (tmp_fd)) == NOTOK) {
  211.     close (tmp_fd);
  212.     return MFERR;
  213.     }
  214.     if ((tmp = fdopen (fd, "w")) == NULL) {
  215.     close (tmp_fd);
  216.     close (fd);
  217.     return MFERR;
  218.     }
  219.  
  220.     for (;;) {
  221.     switch (do_header (from, date, in, tmp)) {
  222.         case NOTOK: 
  223.         close (tmp_fd);
  224.         fclose (tmp);
  225.         return MFHDR;
  226.  
  227.         case OK: 
  228.         continue;
  229.  
  230.         case DONE: 
  231.         fclose (tmp);
  232.         break;
  233.     }
  234.     break;
  235.     }
  236.  
  237. /*   */
  238.  
  239.     if (*date == NULL || *from == NULL) {
  240.     if (*date)
  241.         strcpy (buffer, "No (valid) From: field found in message\n");
  242.     else
  243.         if (*from)
  244.         strcpy (buffer, "No (valid) Date: field found in message\n");
  245.         else
  246.         strcpy (buffer,
  247.             "No (valid) From: or Date: fields found in message\n");
  248.     if (nodelim) {
  249.         if (*date == NULL) {
  250.         long clock;
  251.  
  252.         time (&clock);
  253.         sprintf (date, "%.24s", ctime (&clock));
  254.         }
  255.         if (*from == NULL)
  256.         sprintf (from, "%s!%s", SystemName (), getusr ());
  257.     }
  258.     else
  259.         return MFHDR;
  260.     }
  261.     else
  262.     buffer[0] = NULL;
  263.     
  264.     if (nodelim && (cp = index (from, '!')) != NULL) {
  265.     *cp++ = NULL;
  266.     fprintf (out, "From %s %s remote from %s\n", cp, date, from);
  267.     }
  268.     else
  269.     fprintf (out, "From %s %s\n", from, date);
  270.  
  271.     fprintf (out, "Munged: from %s to %s; %s\n",
  272.         LocalName (), SystemName (), dtimenow ());
  273.     if (buffer[0])
  274.     fprintf (out, "Illegal-Field: %s", buffer);
  275.     
  276.     if ((tmp = fdopen (tmp_fd, "r")) == NULL) {
  277.     close (tmp_fd);
  278.     return MFERR;
  279.     }
  280.     fseek (tmp, 0L, 0);
  281.  
  282.     while ((i = fread (line, sizeof *line, sizeof line, tmp)) > 0)
  283.     fwrite (line, sizeof *line, i, out);
  284.     putc ('\n', out);        /* separate headers from body */
  285.     fclose (tmp);
  286.  
  287.     return OK;
  288. }
  289.  
  290. /*   */
  291.  
  292. static int  mmdf_text (in, out, nodelim)
  293. int     nodelim;
  294. FILE * in, *out;
  295. {
  296.     int     i;
  297.  
  298.     if (feof (in))        /* probably no body */
  299.     putc ('\n', out);
  300.     else
  301.     while ((i = fread (buffer, sizeof *buffer, sizeof buffer, in)) > 0)
  302.         fwrite (buffer, sizeof *buffer, i, out);
  303.  
  304.     if (!nodelim)
  305.     putc ('\n', out);
  306.     fclose (in);
  307.  
  308.     return OK;
  309. }
  310.  
  311. /*   */
  312.  
  313. static int  do_header (from, date, in, out)
  314. char   *from,
  315.        *date;
  316. FILE * in, *out;
  317. {
  318.     int     i,
  319.             margin,
  320.             some,
  321.             spat,
  322.             pos;
  323.     char   *bp,
  324.            *cp,
  325.            *pp,
  326.             line[BUFSIZ];
  327.     struct adrx *adrxp;
  328.     struct header  *hl;
  329.  
  330.     if ((i = mfgets (in, &bp)) != OK)
  331.     return i;
  332.  
  333.     if ((cp = index (bp, ':')) == NULL) {
  334.     fprintf (out, "Illegal-Field: %s\n", bp);
  335.     return OK;
  336.     }
  337.  
  338.     *cp = NULL;
  339.     for (hl = &headers[0]; hl -> h_name; hl++)
  340.     if (lequal (hl -> h_name, bp))
  341.         break;
  342.  
  343. /*   */
  344.  
  345.     switch (hl -> h_type) {
  346.     case HOTHR: 
  347.         *cp = ':';
  348.         fprintf (out, "%s\n", bp);
  349.         break;
  350.  
  351.     case HDATE: 
  352.         pp = ++cp;
  353.         if (*date != NULL || !lequal (hl -> h_name, "Date"))
  354.         return OK;
  355.         date_convert (pp, date);
  356.         if (*date == NULL)
  357.         fprintf (out,
  358.             "Illegal-Object: %s: %s -- illegal date construct\n",
  359.             hl -> h_name, pp);
  360.         break;
  361.  
  362.     case HFROM: 
  363.         pp = ++cp;
  364.         if (*from != NULL)
  365.         return OK;
  366.         if ((adrxp = getadrx (pp)) == NULL) {
  367.         fprintf (out, "Illegal-Object: %s: %s -- %s\n",
  368.             hl -> h_name, pp, "no address");
  369.         return OK;    /* catch errors later (possibly) */
  370.         }
  371.         addr_convert (adrxp, from, TRUE);
  372.         if (*from == NULL)
  373.         fprintf (out, "Illegal-Object: %s: %s -- %s\n",
  374.             hl -> h_name, adrxp -> text, adrxp -> err);
  375.         while (getadrx (NULL))
  376.         continue;
  377.         break;
  378.  
  379.     case HADDR: 
  380.     case HSNDR: 
  381.         spat = 0;
  382.         some = FALSE;
  383.         pp = ++cp;
  384.         margin = pos = strlen (hl -> h_name) + 2;
  385.         while (adrxp = getadrx (pp)) {
  386.         addr_convert (adrxp, line, FALSE);
  387.         if (line[0] != NULL) {
  388.             if (!spat++)
  389.             fprintf (out, "%s: ", hl -> h_name);
  390.             if (some++)
  391.             fputs (", ", out), pos += 2;
  392.             if (pos + strlen (line) >= OWIDTH) {
  393.             fprintf (out, "\n%*s", margin, " ");
  394.             pos = margin;
  395.             }
  396.             fputs (line, out);
  397.             pos += strlen (line);
  398.         }
  399.         else {
  400.             if (spat)
  401.             putc ('\n', out);
  402.             fprintf (out, "Illegal-Object: %s: %s -- %s\n",
  403.                 hl -> h_name, adrxp -> text, adrxp -> err);
  404.             spat = 0;
  405.             some = FALSE;
  406.             pos = margin;
  407.         }
  408.         }
  409.         if (spat)
  410.         putc ('\n', out);
  411.         break;
  412.  
  413.     default: 
  414.         return NOTOK;
  415.     }
  416.  
  417.     return OK;
  418. }
  419.  
  420. /*   */
  421.  
  422. static addr_convert (adrxp, to, notice)
  423. struct adrx *adrxp;
  424. char   *to;
  425. int     notice;
  426. {
  427.     int     mboxlen,
  428.             uucplen;
  429.     char   *cp,
  430.             tmp[LINESIZ],
  431.             uucp[LINESIZ];
  432.     static char path[LINESIZ] = "";
  433.  
  434.     if (path[0] == NULL)
  435.     strcpy (path, LocalName ());
  436.  
  437.     if (adrxp -> err || !adrxp -> mbox) {
  438.     *to = NULL;
  439.     return;
  440.     }
  441.     if (notice)
  442.     strcpy (path, adrxp -> host ? adrxp -> host : LocalName ());
  443.  
  444.     if (adrxp -> host == NULL)
  445.     if (index (adrxp -> mbox, '!') != NULL)
  446.         strcpy (tmp, adrxp -> mbox);
  447.     else
  448.         if (lequal (path, LocalName ()))
  449.         sprintf (tmp, "%s!%s", SystemName (), adrxp -> mbox);
  450.         else
  451.         sprintf (tmp, "%s!%s@%s", SystemName (), adrxp -> mbox, path);
  452.     else
  453.     if (index (adrxp -> mbox, '!') == NULL)
  454.         sprintf (tmp, "%s!%s@%s",
  455.             SystemName (), adrxp -> mbox, adrxp -> host);
  456.     else {
  457.         sprintf (uucp, "%%%s", UucpChan ());
  458.         uucplen = strlen (uucp);
  459.         cp = (lequal (LocalName (), adrxp -> host)
  460.             && (mboxlen = strlen (adrxp -> mbox) - uucplen) > 0)
  461.         ? (adrxp -> mbox) + mboxlen : NULL;
  462.         if (lequal (uucp, cp))
  463.         sprintf (tmp, "%.*s", mboxlen, adrxp -> mbox);
  464.         else
  465.         if ((cp = index (adrxp -> host, '.'))
  466.             && lequal (UucpChan (), cp + 1))
  467.             sprintf (tmp, "%.*s!%s",
  468.             cp - adrxp -> host, adrxp -> host, adrxp -> mbox);
  469.         else
  470.         if (lequal (adrxp -> host, UucpChan ()))
  471.             strcpy (tmp, adrxp -> mbox);
  472.         else {
  473.         sprintf (uucp, "%s!", SystemName ());
  474.         uucplen = strlen (uucp);
  475.         if (strncmp (uucp, adrxp -> mbox, uucplen))
  476.             sprintf (tmp, "%s!%s@%s",
  477.                 SystemName (), adrxp -> mbox, adrxp -> host);
  478.         else
  479.             sprintf (tmp, "%s@%s", adrxp -> mbox, adrxp -> host);
  480.         }
  481.     }
  482.  
  483.     strcpy (to, tmp);
  484. }
  485.  
  486. /*   */
  487.  
  488. static  date_convert (from, to)
  489. char   *from,
  490.        *to;
  491. {
  492.     char   *cp;
  493.  
  494.     if ((cp = dctime (dparsetime (from))) != NULL)
  495.     sprintf (to, "%.24s", cp);
  496.     else
  497.     *to = NULL;
  498. }
  499.  
  500. /*   */
  501.  
  502. static int  mmdf_die (error, in1, in2, out, nodelim)
  503. int     error,
  504.         nodelim;
  505. FILE * in1, *in2, *out;
  506. {
  507.     int     i;
  508.     long    clock;
  509.     char    date[LINESIZ];
  510.  
  511.     if (nodelim) {
  512.     fclose (in1);
  513.     return error;
  514.     }
  515.  
  516.     switch (error) {
  517.     case MFTXT: 
  518.         putc ('\n', out);
  519.         break;
  520.     }
  521.  
  522.     time (&clock);
  523.     sprintf (date, "%.24s", ctime (&clock));
  524.     fprintf (out, "From %s %s\nSubject: %s %s\n\n",
  525.         getusr (), date, "Bad MMDF mailbox - error in",
  526.         error == MFHDR ? "Header" : error == MFTXT ? "Body" : "Mailbox");
  527.  
  528.     fprintf (out, "%s: %s\n%s\n--------\n",
  529.         "Error detected at line", buffer, "Message being processed");
  530.     fseek (in1, 0L, 0);
  531.     while ((i = fread (buffer, sizeof *buffer, sizeof buffer, in1)) > 0)
  532.     fwrite (buffer, sizeof *buffer, i, out);
  533.     fclose (in1);
  534.  
  535.     if (!feof (in2)) {
  536.     fprintf (out, "--------\n%s\n--------\n%s",
  537.         "Remainder of unfiltered mailbox follows", tmpbuf);
  538.     while ((i = fread (buffer, sizeof *buffer, sizeof buffer, in2)) > 0)
  539.         fwrite (buffer, sizeof *buffer, i, out);
  540.     }
  541.  
  542.     fprintf (out, "--------\n\n");
  543.     fflush (out);
  544.  
  545.     return error;
  546. }
  547.